package com.googlecode.framework.core.io;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.Set;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;

import com.googlecode.framework.security.AllHostnameVerifier;

/**
 * 读取http url的数据，辅助项目中一些简单的http读取 复杂的可以使用HttpClient
 * 
 */
public class HttpReader {

    public static final String GET = "GET";

    public static final String POST = "POST";
    
    public static final String DEFAULT_ENCODING = "UTF-8";

    private URL url;

    private String method;

    private HostnameVerifier hostnameVerifier = AllHostnameVerifier.INSTANCE;

    public HttpReader(String url) throws IOException {
        this(new URL(url), GET);
    }
    
    public HttpReader(URL url) throws IOException {
        this(url, GET);
    }
    
    public HttpReader(String url, String method) throws IOException {
        this(new URL(url), method);
    }

    public HttpReader(URL url, String method) throws IOException {
        this.url = url;
        this.method = method;
    }

    public String read() throws IOException {
        return read(null, null, Charset.forName(DEFAULT_ENCODING));
    }

    /**
     * 读取Http Url的数据
     * @param writeData
     * @param requestProperties
     * @param encoding
     * @return
     * @throws IOException
     */
    public String read(String writeData, Map<String, String> requestProperties, Charset encoding) throws IOException {
        HttpURLConnection urlConnection = null;
        BufferedReader httpReader = null;
        BufferedWriter httpWriter = null;
        try {
            urlConnection = (HttpURLConnection) url.openConnection();
            // 初始化
            initHttpConnection(urlConnection, (writeData == null), requestProperties);
            urlConnection.connect();
            if (writeData != null) {
                httpWriter = new BufferedWriter(new OutputStreamWriter(urlConnection.getOutputStream(), encoding));
                httpWriter.write(writeData);
                httpWriter.flush();
            }
//            if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                httpReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), encoding));
                String line = null;
                StringBuilder buf = new StringBuilder();
                while ((line = httpReader.readLine()) != null) {
                    buf.append(line);
                }
                return buf.toString();
//            } else {
//                return null;
//            }
        } finally {
            closeQuietly(httpWriter);
            closeQuietly(httpReader);
            if (urlConnection != null) {
                urlConnection.disconnect();
                urlConnection = null;
            }
        }
    }

    public void setHostnameVerifier(HostnameVerifier hostnameVerifier) {
        this.hostnameVerifier = hostnameVerifier;
    }

    /*
     * 初始化Http连接
     */
    private void initHttpConnection(HttpURLConnection urlConnection, boolean dooutput, Map<String, String> requestProperties) throws IOException {
        if (urlConnection == null) {
            return;
        }
        if (urlConnection instanceof HttpsURLConnection) {
            ((HttpsURLConnection) urlConnection).setHostnameVerifier(this.hostnameVerifier);
        }
        urlConnection.setDoInput(true);
        urlConnection.setDoOutput(dooutput);
        urlConnection.setUseCaches(false);
        urlConnection.setRequestMethod(this.method);
        urlConnection.setInstanceFollowRedirects(true);
        // HTTP1.1
        urlConnection.setRequestProperty("Connection", "close");
        if (requestProperties != null) {
            Set<Map.Entry<String, String>> entries = requestProperties.entrySet();
            for (Map.Entry<String, String> entry : entries) {
                urlConnection.setRequestProperty(entry.getKey(), entry.getValue());
            }
        }
    }
    
    protected void closeQuietly(Closeable closeable) {
        try {
            if (closeable != null) {
                closeable.close();
            }
        } catch (IOException ioe) {
            // ignore
        }
    }
}